﻿package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.ByteArray;
	
	/**
	 * ...
	 * @author Julian Garamendy - Miniclip LTD
	 */
	public class Main extends Sprite 
	{
		private var _eca:ElementaryCellularAutomaton;
		private var _bmp:Bitmap;
		private var _rule:uint = 0;
		private var _bits:uint = 128;
		private var _frmCnt:uint;
		
		private var _colours:Array = [0xFFFFFF, 0x000000];
		private var _txt:TextField;

		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			createECA();
			createBitmap();
			createTextField();
			
			addEventListener( Event.ENTER_FRAME, handleEnterFrame );
			stage.addEventListener( KeyboardEvent.KEY_DOWN, handleKeyDown );
		}
		
		private function createECA():void
		{
			_eca = new ElementaryCellularAutomaton(_bits, _rule, null);
			//_eca.state.writeBoolean(true);
			setRandomState();
		}
		
		private function createBitmap():void
		{
			var scale:Number = 1;
			var w:uint = Math.min(_eca.length, stage.stageWidth / scale);
			var h:uint = Math.min(_eca.length, stage.stageHeight / scale);
			var bmpData:BitmapData = new BitmapData(w, h, false, 0xFFFFFF);
			_bmp = new Bitmap( bmpData );
			_bmp.scaleX = _bmp.scaleY = scale;
			addChild( _bmp );			
		}
		
		private function createTextField():void 
		{
			_txt = new TextField();
			var tf:TextFormat = new TextFormat();
			tf.font = "Verdana";
			tf.size = 10;
			tf.color = 0x000000;
			_txt.defaultTextFormat = tf;
			_txt.selectable = false;
			_txt.height = 16;
			_txt.y = stage.stageHeight - _txt.height;
			addChild( _txt );
		}
		
		private function setRandomRule():void 
		{
			_eca.rule = Math.floor( Math.random() * 256 );
			_txt.text = String( _eca.rule );
		}
		
		private function setRandomState():void 
		{
			var n:uint = _eca.length;
			var st:ByteArray = _eca.state;
			st.position = 0;
			for (var i:int = 0; i < n; i++) 
			{
				var b:Boolean = (Math.random() > .5);
				_eca.state.writeBoolean( b );
			}
			
		}
		private function setRandomColours():void 
		{
			_colours[1] = _colours[0];			
			_colours[0] = Math.random() * 0xFFFFFF;
		}
		private function handleKeyDown(e:KeyboardEvent):void 
		{
			trace( e.keyCode );
			switch (e.keyCode) 
			{
				case 32:
					nextRule();
					break;
				case 67:
					setRandomState();
					break;
			}
		}
			
		private function updateBitmap():void
		{			
			var data:BitmapData = _bmp.bitmapData;
			
			data.scroll(0, -1);
			
			var n:uint = _eca.length;
			_eca.state.position = 0;
			
			//trace("n:", n);
			for (var i:int = 0; i < n; i++) 
			{
				//trace("i:", i);
				var indx:uint = ( _eca.state.readBoolean() ) ?  1 : 0;
				var colour:uint = _colours[ indx ];
				data.setPixel(data.width - i, data.height-1, colour );
			}
			
		}
		
		
		private function handleEnterFrame(e:Event):void 
		{
			if (_frmCnt >= _eca.length*2 && true) 
			{
				//nextRule();
				_frmCnt = 0;
			}
			updateBitmap();
			_eca.update();
			_frmCnt++;
		}		
		
		private function nextRule():void 
		{
			//setRandomRule();
			_eca.rule++;
			_txt.text = String( _eca.rule );			
			
			setRandomState();
			//setRandomColours();
		}
		
		/*
		18
		22
		30
		45
		54
		60 *
		75
		82
		86
		90 *
		102
		105
		106
		110
		120
		122
		124
		126
		129
		135
		137
		146
		147
		149
		150
		151
		153
		154
		161
		165
		166
		169
		181
		182
		183
		193
		195
		210
		225	
		*/
	}
	
}